package com.my.study.springframework.bean.factory.support;

import com.my.study.springframework.bean.BeansException;
import com.my.study.springframework.bean.factory.FactoryBean;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: yidujun
 * @create: 2021/07/12 13:44
 */
public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanRegistry {

    /**
     * Cache of singleton objects created by FactoryBeans: FactoryBean name to object.
     */
    private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

    protected Object getCachedObjectForFactoryBean(String name) {
        Object obj = this.factoryBeanObjectCache.get(name);
        return obj != NULL_OBJECT ? obj : null;
    }

    protected Object getObjectFromFactoryBean(FactoryBean<?> factoryBean, String beanName) {
        if (factoryBean.isSingleton()) {
            Object obj = this.factoryBeanObjectCache.get(beanName);
            if (null == obj) {
                obj = doGetObjectFromFactoryBean(factoryBean, beanName);
                this.factoryBeanObjectCache.put(beanName, obj != null ? obj : NULL_OBJECT);
            }
            return obj;
        }
        else {
            return doGetObjectFromFactoryBean(factoryBean, beanName);
        }
    }

    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factoryBean, final String beanName) {
        try {
            return factoryBean.getObject();
        } catch (Exception e) {
            throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", e);
        }
    }


}
